package com.vtquang.mymaps;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import android.util.Log;

import com.google.android.maps.GeoPoint;

public class WebProvider {
	static String pathPlaceNear = "https://maps.googleapis.com/maps/api/place/search/xml?location={0}&radius={1}&types={2}&sensor=false&key=AIzaSyC0nPWcSTEIsQmHiTCA3Wghz5Ft_bI_7jo";
	static String pathWeather = "http://free.worldweatheronline.com/feed/weather.ashx?q={0}&format=xml&num_of_days={1}&key=61c9855e37163241131901";
	static String pathDirection = "http://maps.googleapis.com/maps/api/directions/xml?origin={0},{1}&destination={2},{3}&language=vi&sensor=false&units=metric&mode={4}";
	static String  pathPanoramio = "http://www.panoramio.com/map/get_panoramas.php?set=public&from=0&to=20&minx={0}&miny={1}&maxx={2}&maxy={3}&size=medium&mapfilter=true";
	
	static List<MyLocation> getLocation(String type, String lat, String lon, int distance) {
		List<MyLocation> list = new ArrayList<MyLocation>();

		String u = pathPlaceNear.replace("{0}", lat.toString() + "," + lon.toString())
								.replace("{1}", String.valueOf(distance))
								.replace("{2}", type);
								
		try {
			HttpClient httpclient = new DefaultHttpClient();
			HttpResponse response = httpclient.execute(new HttpGet(u));
			StatusLine statusLine = response.getStatusLine();
			if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
				ByteArrayOutputStream out = new ByteArrayOutputStream();
				response.getEntity().writeTo(out);
				out.close();
				String responseString = out.toString();
				try {
					InputSource is = new InputSource(new StringReader(
							responseString));
					SAXParserFactory factory = SAXParserFactory.newInstance();
					SAXParser parser = factory.newSAXParser();
					XMLReader reader = parser.getXMLReader();
					XMLParseLocation xfh = new XMLParseLocation(Double.parseDouble(lon), Double.parseDouble(lat));
					reader.setContentHandler(xfh);

					reader.parse(is);
					list = xfh.getListLocation();

				} catch (Exception e) {

				}
			}
		} catch (ClientProtocolException e) {
			// TODO Handle problems..
		} catch (IOException e) {
			// TODO Handle problems..
		}
		return list;
	}

	static ArrayList<WeatherInformation>  getListWeather(String lat, String lon, int nday) {
		ArrayList<WeatherInformation>  list = new ArrayList<WeatherInformation>();

		String u = pathWeather.replace("{0}", lat + "," + lon)
				.replace("{1}", String.valueOf(nday));
		try {
			HttpClient httpclient = new DefaultHttpClient();
			HttpResponse response = httpclient.execute(new HttpGet(u));
			StatusLine statusLine = response.getStatusLine();
			if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
				ByteArrayOutputStream out = new ByteArrayOutputStream();
				response.getEntity().writeTo(out);
				out.close();
				String responseString = out.toString();
				try {
					InputSource is = new InputSource(new StringReader(responseString));
					SAXParserFactory factory = SAXParserFactory.newInstance();
					SAXParser parser = factory.newSAXParser();
					XMLReader reader = parser.getXMLReader();
					XMLParseWeatherInformation xfh = new XMLParseWeatherInformation();
					reader.setContentHandler(xfh);

					reader.parse(is);
					list = xfh.getListWeatherInformation();

				} catch (Exception e) {
				}
			}
		} catch (ClientProtocolException e) {
			// TODO Handle problems..
		} catch (IOException e) {
			// TODO Handle problems..
		}
		return list;
	}
	
	
	public static Direction getDirections(double lat1, double lon1, double lat2, double lon2, String mode) {
		String url = pathDirection.replace("{0}", String.valueOf(lat1))
								  .replace("{1}", String.valueOf(lon1))
								  .replace("{2}", String.valueOf(lat2))
								  .replace("{3}", String.valueOf(lon2))
								  .replace("{4}", mode); 
		HttpResponse response = null;
		Direction dir = new Direction();
		try {
			DefaultHttpClient client = new DefaultHttpClient();
			HttpGet methodGet = new HttpGet(new URI(url));
			response = client.execute(methodGet);
			InputStream in = response.getEntity().getContent();

			DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document doc = builder.parse(in);
			dir = getDirection(doc);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return dir;
	}
	
	private static Direction getDirection(Document doc){
		Direction dir = new Direction();
		ArrayList<StepDirection> lstStep = new ArrayList<StepDirection>(); 

		if (doc != null) {
			Element status = (Element) doc.getElementsByTagName("status").item(0);
			if (status.getTextContent().equals("OK")) {
				NodeList listStep = doc.getElementsByTagName("step");
				int count = listStep.getLength();
				for (int i = 0; i < count; i++) {
					Element step = (Element) listStep.item(i);
					Element duration = (Element) step.getElementsByTagName("duration").item(0);
					Element text_duration = (Element) duration.getElementsByTagName("text").item(0);
					Element instructions = (Element) step.getElementsByTagName("html_instructions").item(0);
					Element distance = (Element) step.getElementsByTagName("distance").item(0);
					Element text_distance = (Element) distance.getElementsByTagName("text").item(0);

					StepDirection stepDir = new StepDirection();
					stepDir.set_distance(text_distance.getTextContent()
							.replaceAll("\n", ""));
					stepDir.set_duration(text_duration.getTextContent()
							.replaceAll("\n", ""));
					stepDir.set_instructions(instructions.getTextContent()
							.replaceAll("\n", ""));

					lstStep.add(stepDir);
				}

				Element startAddress = (Element) doc.getElementsByTagName(
						"start_address").item(0);
				Element endAddress = (Element) doc.getElementsByTagName(
						"end_address").item(0);

				NodeList lstDistance = doc.getElementsByTagName("distance");
				Element totalDistance = (Element) lstDistance.item(lstDistance
						.getLength() - 1);
				Element text_totalDistance = (Element) totalDistance
						.getElementsByTagName("text").item(0);

				NodeList lstDuration = doc.getElementsByTagName("duration");
				Element totalDuration = (Element) lstDuration.item(lstDistance
						.getLength() - 1);
				Element text_totalDuration = (Element) totalDuration
						.getElementsByTagName("text").item(0);

				NodeList nodelist_path = doc
						.getElementsByTagName("overview_polyline");
				Element node_path = (Element) nodelist_path.item(0);
				NodeList nodelist_point = node_path
						.getElementsByTagName("points");
				Node node_point = nodelist_point.item(0);

				dir._startAddress = startAddress.getTextContent();
				dir._endAdress = endAddress.getTextContent();
				dir._totalDistance = text_totalDistance.getTextContent();
				dir._totalDuration = text_totalDuration.getTextContent();
				dir._polyLine = node_point.getTextContent();
				dir._lstStep = lstStep;
			}
		} 
		
		return dir;
	}
	
	public static PanoramioInformation getPanoramino(double lat, double lng){
		PanoramioInformation pano = new PanoramioInformation();
		int min_x = (int)lng - 1;
		int max_x = (int)lng + 1;
		int min_y = (int)lat - 1;
		int max_y = (int)lat + 1;
		String url = pathPanoramio.replace("{0}", String.valueOf(min_x))
								  .replace("{1}", String.valueOf(min_y))
								  .replace("{2}", String.valueOf(max_x))
								  .replace("{3}", String.valueOf(max_y));
		
		InputStream is = null;
		String json = null;
		try {
			DefaultHttpClient client = new DefaultHttpClient();
			HttpGet methodGet = new HttpGet(new URI(url));
			HttpResponse response = client.execute(methodGet);
			is = response.getEntity().getContent();
 
		} catch (Exception e) {
			e.printStackTrace();
			Log.e("haizzz", "Khong lay dc " + e.toString() + "\n" + url);
		}

		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					is, "iso-8859-1"), 8);
			StringBuilder sb = new StringBuilder();
			String line = null;
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
			is.close();
			json = sb.toString();
		} catch (Exception e) {
			Log.e("Buffer Error", "Error converting result " + e.toString());
		}

		try {
			JSONObject jObj = new JSONObject(json);
			pano = new PanoramioInformation(jObj);
		} catch (JSONException e) {
			Log.e("JSON Parser", "Error parsing data " + e.toString());
		}

		return pano;
	}
	
	public static ArrayList<GeoPoint> decodePoly(String encoded) {
		ArrayList<GeoPoint> poly = new ArrayList<GeoPoint>();
		int index = 0, len = encoded.length();
		int lat = 0, lng = 0;

		while (index < len) {
			int b, shift = 0, result = 0;
			do {
				b = encoded.charAt(index++) - 63;
				result |= (b & 0x1f) << shift;
				shift += 5;
			} while (b >= 0x20);
			int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
			lat += dlat;

			shift = 0;
			result = 0;
			do {
				b = encoded.charAt(index++) - 63;
				result |= (b & 0x1f) << shift;
				shift += 5;
			} while (b >= 0x20);
			int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
			lng += dlng;

			GeoPoint p = new GeoPoint((int) (((double) lat / 1E5) * 1E6),
					(int) (((double) lng / 1E5) * 1E6));
			poly.add(p);
		}

		return poly;
	}
}
